package com.info.zhiduoduo.core.dto.operationlog;

import com.baomidou.mybatisplus.activerecord.Model;
import com.info.zhiduoduo.common.annotation.ZddLog;
import com.info.zhiduoduo.common.annotation.LogEntity;
import com.info.zhiduoduo.common.constants.system.ZddAppEnum;
import com.info.zhiduoduo.common.utils.ReflectionUtil;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class OperationLogContext {

	/** 当前操作人信息 */
	OperatorInfo operatorInfo;

	/** 接口方法上的注解 */
	ZddLog zddLog;

	/** 当前处理操作日志的应用平台 */
	ZddAppEnum zddAppEnum;

	/** 切片AOP对象 */
	ProceedingJoinPoint proceedingJoinPoint;

	/** 当前调用的Controller的AOP方法签名 */
	MethodSignature methodSignature;

	/** 请求url */
	String url;

	/** 当前调用的Controller接口方法 */
	Method method;

	/** 当前调用的Controller接口所有的请求参数实际值对象 */
	Object[] args;

	/** url请求参数 */
	String urlParams;

	/** 当前调用的Controller接口方法的请求参数requestBody */
	Object requestBody;

	/** 接口操作之前的原始Entity数据对象map */
	Map<Class<? extends Model<?>>, List<Model<?>>> initialEntities;

	/** 查询对应Entity数据对象的参数。使用Mybatis-plus的Model.selectOne()方法 */
	Map<Class<? extends Model<?>>, List<Map<String, Object>>> initialParameters;

	/** 剩余需要处理的依赖与其他initialEntities的depenOnEntities */
	Map<Class<? extends Model<?>>, LogEntity> pendingDependOnEntities;

	public static OperationLogContext of(ZddLog zddLog, ZddAppEnum zddAppEnum, ProceedingJoinPoint jp, String url, String urlParams) {

		Object[] args = jp.getArgs();
		MethodSignature ms = (MethodSignature) jp.getSignature();
		Method method = ms.getMethod();
		Parameter[] parameters = method.getParameters();
		Object requestBody = ReflectionUtil.findRequestBody(args, parameters);

		return new OperationLogContext().setZddLog(zddLog)
				.setZddAppEnum(zddAppEnum)
				.setProceedingJoinPoint(jp)
				.setMethodSignature(ms)
				.setMethod(method)
				.setUrl(url)
				.setUrlParams(urlParams)
				.setArgs(jp.getArgs())
				.setRequestBody(requestBody)
				.setPendingDependOnEntities(new HashMap<>())
				.setInitialEntities(new HashMap<>())
				.setInitialParameters(new HashMap<>());
	}
}
